#include "sys.h"

/**
  * @brief  初始化STM32时钟系统
  * @param  p11n: PLL倍频系数，决定系统主时钟频率
  * @note   使用HSE作为时钟源，通过PLL倍频后作为系统时钟
  *         配置AHB/APB总线分频器
  */
void stm32_clock_init(uint32_t p11n)
{
  // 初始化返回值
  HAL_StatusTypeDef ret = HAL_ERROR;
  
  // 定义并初始化振荡器配置结构体
  RCC_OscInitTypeDef rcc_osc_init = {0};
  // 定义并初始化时钟配置结构体
  RCC_ClkInitTypeDef rcc_clk_init = {0};
  
  // 配置HSE和PLL参数
  rcc_osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 使用HSE作为振荡器
  rcc_osc_init.HSEState = RCC_HSE_ON;                    // 开启HSE
  rcc_osc_init.HSEPredivValue = RCC_HSE_PREDIV_DIV1;     // HSE预分频为1
  rcc_osc_init.PLL.PLLState = RCC_PLL_ON;                // 开启PLL
  rcc_osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE;        // PLL时钟源选择HSE
  rcc_osc_init.PLL.PLLMUL = p11n;                       // 设置PLL倍频系数
  
  // 应用振荡器配置
  ret = HAL_RCC_OscConfig(&rcc_osc_init);
  
  // 如果配置失败，则进入死循环
  if(ret != HAL_OK){
    while(1);
  }
  
  // 配置系统时钟、总线时钟等
  rcc_clk_init.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 
                           RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); // 配置所有时钟类型
  rcc_clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;   // 系统时钟源选择PLL输出
  rcc_clk_init.AHBCLKDivider = RCC_SYSCLK_DIV1;          // AHB总线不分频
  rcc_clk_init.APB1CLKDivider = RCC_HCLK_DIV2;           // APB1总线2分频
  rcc_clk_init.APB2CLKDivider = RCC_HCLK_DIV1;           // APB2总线不分频
  
  // 应用时钟配置，FLASH延迟设为2个等待周期
  ret = HAL_RCC_ClockConfig(&rcc_clk_init, FLASH_LATENCY_2);
  
  // 如果配置失败，则进入死循环
  if(ret!=HAL_OK){
    while(1);
  }
}